#!/bin/sh
##############################################################
##  Author: cblock@126.com  FergusZeng 2016 ShenZhen,China  ##
##  WARNING:本文件为mbuild系统核心脚本文件，修改时务必谨慎! ##
##############################################################
CPU_NUM=4
HOST=
HOST_FLAGS=
HOST_FNAME=`uname -m`
OUTPUT_DIRECTORY=
PRODUCT_NAME=default
BUILD_SYSTEM=`uname -o | tr '[A-Z]' 'a-z'`;
if [[ $BUILD_SYSTEM =~ "cygwin" ]];then
    BUILD_SYSTEM=OS_CYGWIN
else
    BUILD_SYSTEM=OS_UNIX
fi
function check_make_result()
{
    TIME_STRING=`date`
    if [ "$AUTO_BUILD" == "yes" ];then
        if [ "$3" -ne 0 ];then
            echo "$TIME_STRING | $1 $2 ==> ERROR on $4" >> $PROJECT_ROOT/autobuild.log
            exit
        else
            echo "$TIME_STRING | $1 $2 ==> SUCCESS on $4" >> $PROJECT_ROOT/autobuild.log
        fi
    fi
    if [ "$3" -ne 0 ]; then
        while true
        do
            echo -e "\033[31m\033[1m$TIME_STRING | $1 $2 ==> ERROR on $4, press Ctrl+C to quit!\033[0m";
            read n
        done	
    fi
}
function mbuild_make()
{
    if [ $# -lt 2 -o $# -gt 3 ];then
        echo "[usage] mbuild_make <directory> <target> <libtype>"
        return
    elif [ $# = 3 ];then
        LINK_TYPE=$3
    else
        LINK_TYPE=
    fi
    PNAME="$(echo $PRODUCT_NAME | tr '[:lower:]' '[:upper:]')"
    if [ "$PNAME" == "DEFAULT" ];then
        echo -e "\033[33m\033[1mmbuild_make $1 $2 for HOST: $HOST PRODUCT: not set\033[0m"
    else
        echo -e "\033[33m\033[1mmbuild_make $1 $2 for HOST: $HOST PRODUCT: PRODUCT_$PNAME\033[0m"
    fi
    make pre-build -f compile_tools/core/main.mk SOURCES_DIR=$1 HOST_FLAGS="$HOST_FLAGS" TARGET_NAME=$2 LINK_TYPE=$LINK_TYPE PROJECT_ROOT=$PROJECT_ROOT HOST=$HOST HOST_FNAME=$HOST_FNAME PRODUCT_NAME=$PNAME OUTPUT_DIRECTORY=$OUTPUT_DIRECTORY
    check_make_result $1 $2 $? pre-build
    make all -f compile_tools/core/main.mk -j$CPU_NUM SOURCES_DIR=$1 HOST_FLAGS="$HOST_FLAGS" TARGET_NAME=$2 LINK_TYPE=$LINK_TYPE PROJECT_ROOT=$PROJECT_ROOT HOST=$HOST HOST_FNAME=$HOST_FNAME PRODUCT_NAME=$PNAME OUTPUT_DIRECTORY=$OUTPUT_DIRECTORY
    check_make_result $1 $2 $? build
    make post-build -f compile_tools/core/main.mk SOURCES_DIR=$1 HOST_FLAGS="$HOST_FLAGS" TARGET_NAME=$2 LINK_TYPE=$LINK_TYPE PROJECT_ROOT=$PROJECT_ROOT HOST=$HOST HOST_FNAME=$HOST_FNAME PRODUCT_NAME=$PNAME OUTPUT_DIRECTORY=$OUTPUT_DIRECTORY
    check_make_result $1 $2 $? post-build
}

function mbuild_clean()
{
    if [ $# -lt 2 -o $# -gt 3 ];then
        echo "[usage] mbuild_clean <directory> <target>"
        return
    fi
    PNAME="$(echo $PRODUCT_NAME | tr '[:lower:]' '[:upper:]')"
    if [ "$PNAME" == "DEFAULT" ];then
        echo -e "\033[33m\033[1mmbuild_clean $1 $2 for HOST: $HOST PRODUCT: not set\033[0m"
    else
        echo -e "\033[33m\033[1mmbuild_clean $1 $2 for HOST: $HOST PRODUCT: PRODUCT_$PNAME\033[0m"
    fi
    make clean -f compile_tools/core/main.mk -j$CPU_NUM SOURCES_DIR=$1 TARGET_NAME=$2 PROJECT_ROOT=$PROJECT_ROOT HOST=$HOST HOST_FNAME=$HOST_FNAME PRODUCT_NAME=$PNAME OUTPUT_DIRECTORY=$OUTPUT_DIRECTORY
}

function mbuild_remake()
{
    USAGE_INFO="[usage] mbuild_remake <directory> <target> <libtype>"
    if [ $# -lt 2 -o $# -gt 3 ];then
        echo $USAGE_INFO
        return
    fi
    PNAME="$(echo $PRODUCT_NAME | tr '[:lower:]' '[:upper:]')"
    mbuild_clean $1 $2
    mbuild_make $1 $2 $3
}

# 创建子工程模块
function mbuild_project()
{
    USAGE_INFO="[usage] mbuild_project <directory> <target> [exec|lib|res|qt|fromsrc|fromtar]"
    if [ $# -ne 3 ];then
        echo $USAGE_INFO
        return
    else
        DIR=$1
        PROJ=$2
        TYPE=$3
    fi
    # 检查参数
    if [ "$TYPE" == "exec" -a "$TYPE" == "lib" -a "$TYPE" == "res" -a "$TYPE" == "qt" -a "$TYPE" == "fromsrc" -a "$TYPE" == "fromtar" ];then
        echo $USAGE_INFO
        return
    fi
    # 工程已经存在,则返回
    if [ -f $DIR/$PROJ.mk ];then
        echo "project $DIR/$PROJ.mk allready exist!"
        return
    fi
    # 目录不存在则创建
    if [ ! -d $DIR ];then
        mkdir -p $DIR
    fi
    # 拷贝工程模板
    if [ "$TYPE" == "exec" ];then
        cp compile_tools/templates/target-exec.mk.in $DIR/$PROJ.mk
    elif [ "$TYPE" == "lib" ];then
        cp compile_tools/templates/target-lib.mk.in $DIR/$PROJ.mk
    elif [ "$TYPE" == "res" ];then
        cp compile_tools/templates/target-res.mk.in $DIR/$PROJ.mk
    elif [ "$TYPE" == "qt" ];then
        cp compile_tools/templates/target-qt.mk.in $DIR/$PROJ.mk
    elif [ "$TYPE" == "fromsrc" ];then
        cp compile_tools/templates/from-src.mk.in $DIR/$PROJ.mk
        cp compile_tools/templates/Makefile.mbuild.in $DIR/Makefile.mbuild
    elif [ "$TYPE" == "fromtar" ];then
        cp compile_tools/templates/from-tar.mk.in $DIR/$PROJ.mk
    else
        echo $USAGE_INFO
        return
    fi
    # 编辑模板
    LINE_NUM=`sed -n '/LOCAL_MODULE/=' $DIR/$PROJ.mk`
    sed -i "$LINE_NUM""c\LOCAL_MODULE := $PROJ" $DIR/$PROJ.mk
    echo "create project $DIR/$PROJ.mk ok."
}

# 创建CMakeLists.txt文件
function mbuild_cmake_project()
{
    USAGE_INFO="[usage] mbuild_cmake_project <target_dir> <target_name>"
    if [ $# -ne 2 ];then
        echo $USAGE_INFO
        return
    else
        TARGET_DIR=$1
        TARGET_NAME=$2
    fi

    # 工程已经存在,则返回
    if [ -f "$TARGET_DIR/CMakeLists.txt" ];then
        echo "project $TARGET_DIR/CMakeLists.txt allready exist!"
        return
    fi

    # 目录不存在则创建
    if [ ! -d $TARGET_DIR ];then
        mkdir -p $TARGET_DIR
    fi

    # 拷贝工程模板
    cp compile_tools/templates/CMakeLists.txt.in $TARGET_DIR/CMakeLists.txt

    # 编辑模板
    LINE_NUM=`sed -n '/#project()/=' $TARGET_DIR/CMakeLists.txt`
    sed -i "$LINE_NUM""c\#project($TARGET_NAME)" $TARGET_DIR/CMakeLists.txt

    # 在工程根目录的CMakeLists.txt添加子工程目录
    SUB_DIR=`dirname $TARGET_DIR`"/"`basename $TARGET_DIR`
    sed -i "\#add_subdirectory($SUB_DIR)#d" $PROJECT_ROOT/CMakeLists.txt
    sed -i "\#add_subdirectory($SUB_DIR/)#d" $PROJECT_ROOT/CMakeLists.txt
    echo "add_subdirectory($SUB_DIR)" >> $PROJECT_ROOT/CMakeLists.txt
    echo "create project $TARGET_DIR/CMakeLists.txt ok."
}

function is_empty_dir()
{ 
    if [ "$(ls -A $1)" ];then
        return 0
    else
        return 1
    fi
}

# 一次性构建所有工程
function mbuild_cmake()
{
    USAGE_INFO="[usage] mbuild_cmake <build_dir>"
    if [ $# -ne 1 ];then
        echo $USAGE_INFO
        return
    else
        if [ ! -d $PROJECT_ROOT/$1 ];then
            BUILD_DIR=$PROJECT_ROOT/$1
            mkdir -p $BUILD_DIR
        else
            BUILD_DIR=$PROJECT_ROOT/$1
        fi
    fi
    echo -e "\033[33m\033[1m-----------------------------------------------------------------\033[0m"
    echo -e "\033[33m\033[1mmbuild_cmake <build_dir=$BUILD_DIR>\033[0m"
    cd $BUILD_DIR
    cmake $PROJECT_ROOT
    make
    echo -e "\033[33m\033[1m-----------------------------------------------------------------\033[0m"
    echo -e "\033[33m\033[1mmbuild_cmake install all targets.\033[0m"
    make install
    cd $PROJECT_ROOT
}

# 构建cmake工程
function mbuild_cmake_make()
{
    USAGE_INFO="[usage] mbuild_cmake_make <directory> <build_dir>"
    if [ $# -ne 1 -a $# -ne 2 ];then
        echo $USAGE_INFO
        return
    else
        TARGET_DIR=$1
        if [ $# -eq 1 ];then
            BUILD_DIR=$PROJECT_ROOT/build #默认创建build目录用于构建cmake
        else
            BUILD_DIR=$PROJECT_ROOT/$2
        fi
    fi

    # 判断是否是cmake工程,不是的话按mbuild工程处理
    if [ ! -f "$PROJECT_ROOT/$TARGET_DIR/CMakeLists.txt" ];then
        TARGET=`basename $TARGET_DIR`
        if [ -f "$PROJECT_ROOT/$TARGET_DIR/$TARGET.mk" ];then
            set_output $BUILD_DIR
            mbuild_make $TARGET_DIR $TARGET
            return
        else
            echo "no target in $PROJECT_ROOT/$TARGET_DIR"
            return
        fi
    fi
    
    # 判断构建目录及目标是否存在
    if [ ! -d $BUILD_DIR ];then
        mkdir -p $BUILD_DIR
    else
        is_empty_dir $BUILD_DIR
        if [ $? ];then
            echo "Start build in directory: $BUILD_DIR"
        else
            if  [ -f "$BUILD_DIR/CMakeCache.txt" -a -f "$BUILD_DIR/Makefile" ];then
                echo "Start build in directory: $BUILD_DIR"
            else
                echo "$BUILD_DIR is not a cmake build directory!"
                return
            fi
        fi
    fi
    echo -e "\033[33m\033[1m-----------------------------------------------------------------\033[0m"
    echo -e "\033[33m\033[1mmbuild_cmake_make <target_dir=$TARGET_DIR> <build_dir=$BUILD_DIR>\033[0m"
    cd $BUILD_DIR
    cmake $PROJECT_ROOT
    if [ ! -d $BUILD_DIR/$TARGET_DIR ];then
        echo "no target to make in $BUILD_DIR"
        cd $PROJECT_ROOT
        return
    fi
    make -C $TARGET_DIR
    echo -e "\033[33m\033[1m-----------------------------------------------------------------\033[0m"
    echo -e "\033[33m\033[1mmbuild_cmake_make install target: $TARGET_DIR\033[0m"
    make -C $TARGET_DIR install
    cd $PROJECT_ROOT
}

# 清理cmake工程
function mbuild_cmake_clean()
{
    USAGE_INFO="[usage] mbuild_cmake_clean <directory> <build_dir>"
    if [ $# -ne 1 -a $# -ne 2 ];then
        echo $USAGE_INFO
        return
    else
        TARGET_DIR=$1
        if [ $# -eq 1 ];then
            BUILD_DIR=$PROJECT_ROOT/build #默认为build目录
        else
            BUILD_DIR=$PROJECT_ROOT/$2
        fi
    fi

    # 判断是否是cmake工程,不是的话按mbuild工程处理
    if [ ! -f "$PROJECT_ROOT/$TARGET_DIR/CMakeLists.txt" ];then
        TARGET=`basename $TARGET_DIR`
        if [ -f "$PROJECT_ROOT/$TARGET_DIR/$TARGET.mk" ];then
            set_output $BUILD_DIR
            mbuild_clean $TARGET_DIR $TARGET
            return
        else
            echo "no target in $PROJECT_ROOT/$TARGET_DIR"
            return
        fi
    fi

    # 判断构建目录及目标是否存在
    if [ ! -d $BUILD_DIR ];then
        echo "no cmake build directory: $BUILD_DIR, please run mbuild_cmake_make first!"
        return
    fi
    if [ ! -d $BUILD_DIR/$TARGET ];then
        echo "not cmake target exist: $TARGET_DIR, please run mbuild_cmake_make first!"
        return
    fi
    echo -e "\033[33m\033[1m-----------------------------------------------------------------\033[0m"
    echo -e "\033[33m\033[1mmbuild_cmake_clean <target_dir=$TARGET_DIR> <build_dir=$BUILD_DIR>\033[0m"
    cd $BUILD_DIR
    make -C $TARGET_DIR clean
    cd $PROJECT_ROOT
}